Mortal Kombat 3 "Control a NOOB" hack disassembly notes

--------------------
RAM offsets
--------------------

7E1B7A - Offset for sound FX loadup? (not the final offset, just the initial
         one used, dunno if it handles music as well)

7E1C59 - Fighter in Smoke's slot at character select

7E3626 - Bit 0 set = P1 enabled
7E3630 - Player 1 fighter
7E37E8 - Bit 0 set = P2 enabled
7E37F2 - Player 2 fighter

7E3AC2 - Bit 0 set = Shao Kahn enabled
7E3AC4 - Bit 0 set = Motaro enabled
7E3AC6 - Bit 0 set = Smoke enabled

7E51D6 - Player 1 fighter's moveset
7E51D8 - Player 2 fighter's moveset

Fighter list:

00 - Kano
01 - Sonya
02 - Jax
03 - Nightwolf
04 - Sub-Zero
05 - Stryker
06 - Sindel
07 - Sektor
08 - Cyrax
09 - Kung Lao
0A - Kabal
0B - Sheeva
0C - Shang Tsung
0D - Liu Kang
0E - Smoke
0F - Motaro
10 - Shao Kahn
11 - Noob

--------------------
ASM notes
--------------------

NOTE: This ROM is in HiROM format, reading from 80.

Title screen ASM notes:

Fighter loadup for Smoke code at title screen

$82/D82B A9 0E 00	LDA #$000E  ;Load value for Smoke
$82/D82E 9D D6 51	STA $51D6,x ;Store in P1's moveset

New fighter loadup for Smoke/Noob code at title screen

NOTE: This has been removed in v1.0 as Noob is no longer reliant on Smoke
availability.

$82/D82B A9 11 00	LDA #$0011  ;Load value for Noob
$82/D82E 9D D6 51	STA $51D6,x ;Store in P1's moveset

"Outstanding" sound FX loadup for Smoke code

$82/D86A A9 7E 00	LDA #$007E  ;Load up initial value for accessing SFX
$82/D86D 22 57 D1 83	JSL $83D157 ;Store SFX number to 7E:1B7A

$83/D157 9C 70 1B	STZ $1B70   ;Not relevant for this disasm....
$83/D15A 0A		ASL A       ;Double given value for A,
$83/D15B 69 A8 D4	ADC #$D4A8  ;and add D4A8h to A
$83/D15E 4C 8F D1	JMP $D18F
$83/D18F C2 30		REP #$30    ;Clear M and X flags if necessary
$83/D191 A8		TAY         ;Transfer A to Y for SFX loadup
$83/D192 F4 80 7E	PEA $7E80   ;Not relevant for this disasm AFAIK....
$83/D195 AB		PLB         ;Not relevant for this disasm AFAIK....
$83/D196 0B		PHD         ;Save current D value for later use
$83/D197 A9 00 17	LDA #$1700
$83/D19A 5B		TCD         ;Load D with 1700h for variable loadup
$83/D19B 84 0A		STY $0A     ;Store Y at 7E:170A
$83/D19D A9 86 00	LDA #$0086
$83/D1A0 85 0C		STA $0C     ;Store 86h at 7E:170C
$83/D1A2 A7 0A		LDA [$0A]   ;Load from long address given at 7E:170A
$83/D1A4 29 FF 00	AND #$00FF  ;(which is 86:D5A4), change to 8-bit value,
$83/D1A7 8D 7A 1B	STA $1B7A   ;and store at 7E:1B7A (value is 008Dh)

Modifications for "You suck" sound FX loadup for Smoke/Noob code

NOTE: This has been removed in v1.0 as Noob is no longer reliant on Smoke's
availability.

$82/D86A A9 7E 00	LDA #$007F  ;Load up initial value for accessing SFX
$82/D86D 22 57 D1 83	JSL $83D157 ;Store SFX number to 7E:1B7A

...
$83/D1A2 A7 0A		LDA [$0A]   ;Load from long address given at 7E:170A
$83/D1A4 29 FF 00	AND #$00FF  ;(which is 86:D5A6), change to 8-bit value,
$83/D1A7 8D 7A 1B	STA $1B7A   ;and store at 7E:1B7A (value is 0091h)

Pre-kombat ASM notes:

Test to see if any characters unlocked

NOTE: This decides whether Smoke playability is teased or to switch between
available hidden characters.  The tease code has been disabled entirely in this
hack, as I didn't care to go to the trouble of making it compatible with the
Noob select code. :\

$82/D0A7 AD C6 3A       LDA $3AC6   ;Load Smoke enabled byte
$82/D0AA 0D C2 3A       ORA $3AC2   ;OR with Shao Kahn enabled byte
$82/D0AD 0D C4 3A       ORA $3AC4   ;OR with Motaro enabled byte
$82/D0B0 F0 76          BEQ $D128   ;Branch if none enabled

Modification to disable tease code

$82/D0B0 F0 00          BEQ $D0B2   ;Don't ever branch

Loadup for middle slot at character select screen

$82/D0B2 A9 01 00	LDA #$0001
$82/D0B5 22 D5 FD 86	JSL $86FDD5 ;Not sure....
$82/D0B9 AD C6 3A	LDA $3AC6
$82/D0BC F0 1C		BEQ $D0DA   ;If Smoke is not enabled, branch
$82/D0BE A9 0E 00	LDA #$000E  ;Load Smoke's value and store to middle 
$82/D0C1 8D 59 1C	STA $1C59   ;character slot.
$82/D0C4 F4 D1 82	PEA $82D1
$82/D0C7 F4 00 55	PEA $5500   ;Make slot available?
$82/D0CA 48 		PHA 
$82/D0CB 22 54 FF 86	JSL $86FF54 ;Loads the given pics? (Smoke)
$82/D0CF F4 D1 82	PEA $82D1
$82/D0D2 F4 00 B3	PEA $B300   ;Make slot unavailable?
$82/D0D5 48 		PHA 
$82/D0D6 22 54 FF 86	JSL $86FF54 ;Loads the given pics? (Dragon symbol)
$82/D0DA AD 26 36	LDA $3626
$82/D0DD F0 D3		BEQ $D0B2   ;If P1 not enabled, branch
$82/D0DF AD E8 37	LDA $37E8
$82/D0E2 F0 CE		BEQ $D0B2   ;If P2 not enabled, branch
$82/D0E4 AD C2 3A	LDA $3AC2
$82/D0E7 F0 1C		BEQ $D105   ;If Shao Kahn is not enabled, branch
$82/D0E9 A9 10 00	LDA #$0010  ;Load Kahn's value and store to middle 
$82/D0EC 8D 59 1C	STA $1C59   ;character slot.
$82/D0EF F4 D1 82	PEA $82D1
$82/D0F2 F4 00 55	PEA $5500   ;Make slot available?
$82/D0F5 48 		PHA 
$82/D0F6 22 54 FF 86	JSL $86FF54 ;Loads the given pics? (Shao Kahn)
$82/D0FA F4 D1 82	PEA $82D1
$82/D0FD F4 00 B3	PEA $B300   ;Make slot unavailable?
$82/D100 48 		PHA 
$82/D101 22 54 FF 86	JSL $86FF54 ;Loads the given pics? (Dragon symbol)
$82/D105 AD C4 3A	LDA $3AC4
$82/D108 F0 1C		BEQ $D126   ;If Motaro is not enabled, branch
$82/D10A A9 0F 00	LDA #$000F  ;Load Motaro's value and store to middle
$82/D10D 8D 59 1C	STA $1C59   ;character slot.
$82/D110 F4 D1 82	PEA $82D1
$82/D113 F4 00 55	PEA $5500   ;Make slot available?
$82/D116 48 		PHA 
$82/D117 22 54 FF 86	JSL $86FF54 ;Loads the given pics? (Motaro)
$82/D11B F4 D1 82	PEA $82D1
$82/D11E F4 00 B3	PEA $B300   ;Make slot unavailable?
$82/D121 48 		PHA 
$82/D122 22 54 FF 86	JSL $86FF54 ;Loads the given pics? (Dragon symbol)
$82/D126 80 8A		BRA $D0B2   ;Redo the loop

Modifcations to middle slot loadup to insert Noob

$82/D0DA 5C F4 FB BF	JMP $BFFBF4 ;Jump to controller check/Noob code

$BF/FBF4 AD 26 36	LDA $3626
$BF/FBF7 F0 2A		BEQ $FC23   ;If P1 not enabled, branch
$BF/FBF9 AD E8 37	LDA $37E8
$BF/FBFC F0 25		BEQ $FC23   ;If P2 not enabled, branch
$BF/FBFE AD C6 3A	LDA $3AC6
$BF/FC01 F0 1C		BEQ $FC1F   ;If Smoke/Noob is not enabled, branch
$BF/FC03 A9 11 00	LDA #$0011  ;Load Noob's value and store to middle
$BF/FC06 8D 59 1C	STA $1C59   ;character slot.
$BF/FC09 F4 D1 82	PEA $82D1
$BF/FC0C F4 00 55	PEA $5500   ;Make slot available?
$BF/FC0F 48		PHA
$BF/FC10 22 54 FF 86	JSL $86FF54 ;Loads the given pics? (Noob)
$BF/FC14 F4 D1 82	PEA $82D1
$BF/FC17 F4 00 B3	PEA $B300   ;Make slot unavailable?
$BF/FC1A 48		PHA
$BF/FC1B 22 54 FF 86	JSL $86FF54 ;Loads the given pics? (Dragon symbol)
$BF/FC1F 5C E4 D0 82	JMP $82D0E4 ;Jump to Shao Kahn check
$BF/FC23 5C B2 D0 82	JMP $82D0B2 ;Redo the loop

Player selection overlap check for middle slot (same character highlighted)

$84/E7F4 AD 59 1C	LDA $1C59   ;Load current fighter in middle slot
$84/E7F7 C9 0E 00	CMP #$000E  ;Compare to 0Eh (Smoke)
$84/E7FA D0 08		BNE $E804   ;If not Smoke, do not allow overlap

New player selection overlap check for middle slot (same character highlighted)

$84/E7F4 5C 27 FC BF	JML $BFFC27 ;Jump to $BFFC27
$84/E7F8 EA		NOP
$84/E7F9 EA		NOP         ;Wasted byte cleanup
$84/E7FA EA		NOP
$84/E7FB EA		NOP

Subroutine $BFFC27

$BF/FC27 AD 59 1C	LDA $1C59   ;Load current fighter in middle slot
$BF/FC2A C9 0E 00	CMP #$000E  ;Compare to 0Eh (Smoke)
$BF/FC2D F0 09		BEQ $FC38   ;Allow overlap if Smoke is in middle slot
$BF/FC2F C9 11 00	CMP #$0011  ;Compare to 11h (Noob)
$BF/FC32 F0 08		BEQ $FC3C   ;Allow overlap/disable code check for Noob
$BF/FC34 5C 04 E8 84	JML $84E804 ;Jump to code to prevent highlight overlap
$BF/FC38 5C FC E7 84	JML $84E7FC ;Jump to code to allow highlight overlap
$BF/FC3C 5C 01 E8 84	JML $84E801 ;Jump to code to allow highlight overlap
                                    ;(Ignore Smoke code check)

Vs. screen Motaro/Shao Kahn check

$80/EA48 AE 30 36	LDX $3630   ;Load P1 fighter to X
$80/EA4B AC F2 37	LDY $37F2   ;Load P2 fighter to Y
$80/EA4E A9 10 00	LDA #$0010  ;Load 10h to A
$80/EA51 22 98 EA 83	JSL $83EA98 ;Check 10h (Shao Kahn) against X and Y
$80/EA55 F0 E7		BEQ $EA3E   ;If either = 10h, skip Vs. screen
$80/EA57 A9 0F 00	LDA #$000F  ;Load 0Fh to A
$80/EA5A 22 98 EA 83	JSL $83EA98 ;Check 0Fh (Motaro) against X and Y
$80/EA5E F0 DE		BEQ $EA3E   ;If either = 0Fh, skip Vs. screen

Subroutine $83EA98

$83/EA98 85 12		STA $12     ;Store A to 00:0212
$83/EA9A 86 0A		STX $0A     ;Store P1 fighter to 00:020A
$83/EA9C 84 0E		STY $0E     ;Store P2 fighter to 00:020E
$83/EA9E C5 0A		CMP $0A     ;Compare A against P1 fighter value
$83/EAA0 F0 02		BEQ $02     ;Exit subroutine if match
$83/EAA2 C5 0E		CMP $0E     ;Compare A against P2 fighter value
$83/EAA4 6B		RTL         ;Exit subroutine

New Vs. screen Motaro/Shao Kahn/Noob check

$80/EA48 AE 30 36	LDX $3630   ;Load P1 fighter to X
$80/EA4B AC F2 37	LDY $37F2   ;Load P2 fighter to Y
$80/EA4E A9 0E 00	LDA #$000E  ;Load 0Eh to A
$80/EA51 22 98 EA 83	JSL $83EA98 ;Load values to 00:020A, 020E, and 0212
$80/EA55 C5 0A          CMP $0A     ;Compare A against P1 fighter value
$80/EA57 90 E5          BCC $EA3E   ;Cancel Vs. screen if 00:020A > 0Eh
$80/EA59 C5 0E          CMP $0E     ;Compare A against P2 fighter value
$80/EA5B 90 E1		BCC $EA3E   ;Cancel Vs. screen if 00:020E > 0Eh
$80/EA5D 80 01          BRA $EA60   ;Wasted three bytes cleanup
$80/EA5F EA             NOP

Stage select

NOTE: This is where the Kano -> Noob switch code is installed.  Nothing is
actually done to the stage select itself (the code is essentially the same),
this is just a conveinent place to make the switch.

$80/84F2 AE 30 36       LDX $3630   ;Load P1 fighter to X
$80/84F5 AC F2 37       LDY $37F2   ;Load P2 fighter to Y
$80/84F8 A9 0F 00       LDA #$000F  ;Load A with 0Fh (Motaro)
$80/84FB 22 98 EA 83    JSL $83EA98 ;Compare to see if P1 or P2 is Motaro
$80/84FF D0 06          BNE $8507   ;Branch if neither are Motaro

$80/8507 A9 10 00       LDA #$0010  ;Load A with 10h (Shao Kahn)
$80/850A 22 98 EA 83    JSL $83EA98 ;Compare to see if P1 or P2 is Shao Kahn
$80/850E D0 11          BNE $8521   ;Branch if neither are Shao Kahn

$80/8521 A9 11 00       LDA #$0011  ;Load A with 11h (Noob)
$80/8524 22 98 EA 83    JSL $83EA98 ;Compare to see if P1 or P2 is Noob
$80/8528 D0 06          BNE $8530   ;Branch if neither are Noob

Modifications for Kano -> Noob switch when holding Select

$80/84F2 22 58 FC BF    JSL $BFFC58 ;Jump to Kano -> Noob switch subroutine
$80/84F6 80 00          BRA $84F8   ;Filler code (From here see $80/84F8 above)

Subroutine $BFFC58

$BF/FC58 AF 18 42 00    LDA $004218 ;Load P1 buttons held
$BF/FC5C 29 00 20       AND #$2000  ;AND with 2000h (Select)
$BF/FC5F F0 0B          BEQ $FC6C   ;If P1 Select is not held, branch
$BF/FC61 AD 30 36       LDA $3630   ;Load P1 fighter
$BF/FC64 D0 06          BNE $FC6C   ;Branch if not Kano (00h)
$BF/FC66 A9 11 00       LDA #$0011  ;Load ID for Noob...
$BF/FC69 8D 30 36       STA $3630   ;and make him P1's fighter
$BF/FC6C AF 1A 42 00    LDA $00421A ;Load P2 buttons held
$BF/FC70 29 00 20       AND #$2000  ;AND with 2000h (Select)
$BF/FC73 F0 0B          BEQ $FC80   ;If P2 Select is not held, branch
$BF/FC75 AD F2 37       LDA $37F2   ;Load P2 fighter
$BF/FC78 D0 06          BNE $FC80   ;Branch if not Kano (00h)
$BF/FC7A A9 11 00       LDA #$0011  ;Load ID for Noob...
$BF/FC7D 8D F2 37       STA $37F2   ;and make him P2's fighter
$BF/FC80 AE 30 36       LDX $3630   ;Load P1 fighter to X
$BF/FC83 AC F2 37       LDY $37F2   ;Load P2 fighter to Y
$BF/FC86 6B             RTL         ;Exit subroutine

Kombat ASM notes:

Boss movement check

$84/A42C BC D6 51	LDY $51D6,x ;Load moveset index...
$84/A42F C0 0F 00	CPY #$000F  ;Compare to 0Fh...
$84/A432 90 03		BCC $A437   ;If equal to or greater, don't branch

New boss movement check

$84/A42C 22 3C FC BF	JSL $BFFC40 ;Jump to boss compare subroutine
$84/A430 F0 02          BEQ $A434   ;Branch if Motaro or Shao Kahn
$84/A432 80 03		BRA $A437   ;Branch if not Motaro or Shao Kahn

Subroutine $BFFC40

$BF/FC40 BC D6 51	LDY $51D6,x ;Load moveset index...
$BF/FC43 C0 0F 00	CPY #$000F  ;Compare to 0Fh...
$BF/FC46 F0 03		BEQ $FC4B   ;If equal to, exit subroutine
$BF/FC48 C0 10 00	CPY #$0010  ;Compare to 10h
$BF/FC4B 6B 		RTL         ;Exit subroutine

Boss attack check

$86/E1FB BD D6 51	LDA $51D6,x ;Load moveset index...
$86/E1FE C9 0F 00	CMP #$000F  ;Compare to 0Fh...
$86/E201 B0 0E		BCS $E211   ;If equal to or greater, branch

New boss attack check

$86/E1FB 22 48 FC BF	JSL $BFFC4C ;Jump to boss compare subroutine
$86/E1FF F0 10          BEQ $E211   ;Branch if Motaro or Shao Kahn,
$86/E201 80 00		BRA $E203   ;otherwise, do nothing (this BRA is filler)

Subroutine $BFFC4C

$BF/FC4C BD D6 51	LDA $51D6,x ;Load moveset index...
$BF/FC4F C9 0F 00	CMP #$000F  ;Compare to 0Fh...
$BF/FC52 F0 F7		BEQ $FC4B   ;If equal to, exit subroutine
$BF/FC54 C9 10 00	CMP #$0010  ;Compare to 10h
$BF/FC53 6B 		RTL         ;Exit subroutine

--------------------
Misc. ROM offsets
--------------------

Noob's character select pic

NOTE: This is just a value that leads to pointers(?) in the RAM.  The value 28h
loads up values that, from my tests, always load nothing but completely black
tiles.  I think it's perfect for MK3 Noob, but you can always hack something
better on your own.  AFAIK, this offset in particular isn't used, and the
change has yet to cause any noticable errors.

$82/D06B 28 00 (was 00 00)